#include <iostream>
#include <fstream>
#include <getopt.h>
#include <unistd.h>
#include <string>

using namespace std;

void print_file_with_options(const char* filename, bool number, bool number_nonblank, bool squeeze_blank, bool show_ends, bool show_nonprinting, bool show_tabs) {
    ifstream file(filename);
    if (!file) {
        cerr << "Error: Unable to open file " << filename << endl;
        return;
    }

    string line;
    int line_number = 1;
    bool previous_blank = false;
    while (getline(file, line)) {
        if (squeeze_blank && line.empty() && previous_blank) {
            continue;
        }

        if (number || number_nonblank) {
            if (!line.empty() || !number_nonblank) {
                cerr << line_number << " ";
                line_number++;
            } else {
                cerr << "  ";
            }
        }

        if (show_ends && !line.empty()) {
            line += "$";
        }

        if (show_tabs && !line.empty()) {
            size_t pos = 0;
            while ((pos = line.find("\t", pos)) != string::npos) {
                line.replace(pos, 1, "^I");
                pos += 2; // Adjust position after replacing tab with ^I
            }
        }

        if (show_nonprinting) {
            // Handle non-printing characters
            for (char& c : line) {
                if (!isprint(c)) {
                    c = '^' + (c - 1 + 'A');
                }
            }
        }

        cerr << line << endl;
        previous_blank = line.empty();
    }
}

void printHelp() {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "连接所有指定文件并将结果写到标准输出。" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "cat [选项]...[参数]..." << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "  " << "-A, --show-all" << std::endl;
        std::cerr << "    " << "等效于 -vET" << std::endl;
        std::cerr << "  " << "-b, --number-nonblank" << std::endl;
        std::cerr << "    " << "对非空输出行编号，同时取消 -n 选项效果" << std::endl;
        std::cerr << "  " << "-e" << std::endl;
        std::cerr << "    " << "等效于 -vE" << std::endl;
        std::cerr << "  " << "-E, --show-ends" << std::endl;
        std::cerr << "    " << "在每行结束处显示\"$\"" << std::endl;
        std::cerr << "  " << "-n, --number" << std::endl;
        std::cerr << "    " << "对输出的所有行编号" << std::endl;
        std::cerr << "  " << "-s, --squeeze-blank" << std::endl;
        std::cerr << "    " << "不输出多行空行" << std::endl;
        std::cerr << "  " << "-t" << std::endl;
        std::cerr << "    " << "与 -vT 等效" << std::endl;
        std::cerr << "  " << "-T, --show-tabs" << std::endl;
        std::cerr << "    " << "将跳格字符显示为^I" << std::endl;
        std::cerr << "  " << "-u" << std::endl;
        std::cerr << "    " << "(被忽略)" << std::endl;
        std::cerr << "  " << "-v, --show-nonprinting" << std::endl;
        std::cerr << "    " << "使用^ 和M- 引用，除了LFD和 TAB 之外" << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "[文件名]" << std::endl;
        std::cerr << "    " << "指定打印的文件内容的文件名" << std::endl;
}

int main(int argc, char* argv[]) {
    if(argc == 2 && std::string(argv[1]) == "--help") {
    	printHelp(); // 判断是否输出帮助信息
    	return 0;
    }
    
    int c;
    bool number = false;
    bool number_nonblank = false;
    bool squeeze_blank = false;
    bool show_ends = false;
    bool show_nonprinting = false;
    bool show_tabs = false;

    while ((c = getopt(argc, argv, "benstuvAET")) != -1) {
        switch (c) {
            case 'b': // 对非空行进行编号，空行不进行编号
                number = true;
                number_nonblank = true;
                break;
            case 'e': // 显示文件内容时，在每行的末尾显示换行符（用$表示），同时显示非打印字符
                show_ends = true;
                show_nonprinting = true;
                break;
            case 'n': // 对所有行进行编号
                number = true;
                break;
            case 's': // 压缩连续空行为一行
                squeeze_blank = true;
                break;
            case 't': // 显示制表符（用^I表示），同时显示非打印字符
                show_tabs = true;
                show_nonprinting = true;
                break;
            case 'u': // 提供-u功能，此选项总是生效，但未实现具体功能。
                // This option is provided unconditionally
                break;
            case 'v': // 显示非打印字符。
                show_nonprinting = true;
                break;
            case 'A': // 显示所有特殊字符，包括非打印字符、行尾符和制表符。
                show_nonprinting = true;
                show_ends = true;
                show_tabs = true;
                break;
            case 'E': // 显示文件内容时，在每行的末尾显示换行符（用$表示）。
                show_ends = true;
                break;
            case 'T': // 显示制表符（用^I表示）。
                show_tabs = true;
                break;
            
            default:
                cerr << "Error: Invalid option\n";
                return 1;
        }
    }

    // Process files
    for (int i = optind; i < argc; ++i) {
        print_file_with_options(argv[i], number, number_nonblank, squeeze_blank, show_ends, show_nonprinting, show_tabs);
    }

    // If no files provided, read from standard input
    if (optind == argc) {
        print_file_with_options("-", number, number_nonblank, squeeze_blank, show_ends, show_nonprinting, show_tabs);
    }

    return 0;
}

